/*
 This file is part of Subsonic.

 Subsonic is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Subsonic is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Subsonic.  If not, see <http://www.gnu.org/licenses/>.

 Copyright 2009 (C) Sindre Mehus
 */
package net.nullsum.audinaut.service.parser;

import android.content.Context;
import android.util.Log;
import android.util.Xml;

import net.nullsum.audinaut.R;
import net.nullsum.audinaut.util.ProgressListener;
import net.nullsum.audinaut.util.Util;

import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author Sindre Mehus
 */
abstract class AbstractParser {
    private static final String TAG = AbstractParser.class.getSimpleName();
    private static final String SUBSONIC_RESPONSE = "subsonic-response";

    final Context context;
    private final int instance;
    private XmlPullParser parser;
    private boolean rootElementFound;

    AbstractParser(Context context, int instance) {
        this.context = context;
        this.instance = instance;
    }

    Context getContext() {
        return context;
    }

    void handleError() throws Exception {
        int code = getInteger("code");
        String message;
        switch (code) {
            case 0:
                message = context.getResources().getString(R.string.parser_server_error, get("message"));
                break;
            case 20:
                message = context.getResources().getString(R.string.parser_upgrade_client);
                break;
            case 30:
                message = context.getResources().getString(R.string.parser_upgrade_server);
                break;
            case 40:
                message = context.getResources().getString(R.string.parser_not_authenticated);
                break;
            case 41:
                Util.setBlockTokenUse(context, instance);

                // Throw IOException so RESTMusicService knows to retry
                throw new IOException();
            case 50:
                message = context.getResources().getString(R.string.parser_not_authorized);
                break;
            default:
                message = get("message");
                break;
        }
        throw new SubsonicRESTException(message);
    }

    void updateProgress(ProgressListener progressListener, String message) {
        if (progressListener != null) {
            progressListener.updateProgress(message);
        }
    }

    String getText() {
        return parser.getText();
    }

    String get(String name) {
        return parser.getAttributeValue(null, name);
    }

    boolean getBoolean() {
        return "true".equals(get("isDir"));
    }

    Integer getInteger(String name) {
        String s = get(name);
        try {
            return (s == null || "".equals(s)) ? null : Integer.valueOf(s);
        } catch (Exception e) {
            Log.w(TAG, "Failed to parse " + s + " into integer");
            return null;
        }
    }

    void init(InputStream inputStream) throws Exception {
        parser = Xml.newPullParser();
        parser.setInput(inputStream, "UTF-8");
        rootElementFound = false;
    }

    int nextParseEvent() throws Exception {
        return parser.next();
    }

    String getElementName() {
        String name = parser.getName();
        if (SUBSONIC_RESPONSE.equals(name)) {
            rootElementFound = true;
        }
        return name;
    }

    void validate() throws Exception {
        if (!rootElementFound) {
            throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
        }
    }
}
